

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.util.*;


public class TablePanel extends JPanel implements Scrollable{
	
	private static final int STATE_NORMAL = 0;
	private static final int STATE_SELECT_RECT = 1;
	
	private int state = STATE_NORMAL;
	private SelectionBox selectRectangle;
	
	private Color green = new Color(0.0f, 0.5f, 0.0f);
	private Color red = new Color(0.5f, 0.0f, 0.0f);
	private Color blue = new Color(0.0f, 0.0f, 0.5f);
	private Color purple = new Color(0.25f, 0.0f, 0.25f);
	
	private PlayerModel playerModel;
	private View view;
	
	private Dimension size = new Dimension(800,600);

	private double zoomAmount = 1.0;
	private boolean zoomEnable = true;

	private AffineTransform at = new AffineTransform();
	
	public TablePanel(PlayerModel model, View v) {
		super();
		view = v;
		Dbg.logln("TablePanel Constructor");
		changeBackgroundColour("green");
		MIL mil = new MIL();
		this.addMouseListener(mil);
		this.addMouseMotionListener(mil);
		setPlayer(model);
		updatePanelSize();
		repaint();
	}
	
	private void updatePanelSize(){
		Dimension tablesize = playerModel.getTableSize();
		size = new Dimension((int)(tablesize.width * zoomAmount),(int)(tablesize.height * zoomAmount));
		this.setPreferredSize(size);
		revalidate();
		Dbg.logln("Table Size: " + size.getWidth() + ", " + size.getHeight());
		//view.pack();
		//view.repaint();
		repaint();
	}
	
	public void repaint() {
		Dbg.logln("TablePanel.repaint");
		super.repaint();
	}
	
	public void paintComponent(Graphics g) {
		Dbg.logln("TablePanel.paintComponent");
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		g2d.transform(at);
		
		/*System.out.println("edit border");
		super.paintBorder((Graphics)g2d);*/
		
		if (playerModel==null) return;
		java.util.List<Card> cards = playerModel.getCards();
		// sort by z
		ZComparator.sort(cards);
		
		for (Card card: cards) {			//....2nd time print card image
			CardView.draw(g2d, card, this);
		}
		
		if (state == STATE_SELECT_RECT) {
			g2d.setColor(Color.black);
			g2d.draw(selectRectangle);
		}
		
	}
	/*
	public void paintBorder(Graphics g){
		System.out.println("lkjhgifsd");
		Graphics2D g2d = (Graphics2D)g;
		g2d.transform(at);
		super.paintBorder((Graphics)g2d);
		
	}*/
	
	public void setPlayer(PlayerModel pm){
		playerModel = pm;
		CardView.setModel(pm);
		playerModel.setTablePanel(this);
		repaint();
	}
	/*
	public void forceRepaint() {
		Dbg.logln("TablePanel.forceRepaint");
		// ugly fix for the no-repaint bug
		Graphics g = getGraphics();
		if (g!=null) {
			paintComponent(g);
		} else {
			Dbg.logln("null graphics wtf");
		}
	}*/
	
	public class MIL extends MouseInputAdapter {
		
		public void mousePressed(MouseEvent e) {
			translateMouse(e);
	
			Card selectedCard = null;
			int z = -1;
			Point p = e.getPoint(); //point of click
			
			for(Card card: playerModel.getCards()){
				if(card.getRectangle().contains(p)){//intersects with point
					if(card.getZ() > z){//check if highest z
						z = card.getZ();//set c and z
						selectedCard = card;
					}
				}
			}
			
			state = STATE_NORMAL;
			
			if (selectedCard == null) {	//start selection rectangle
				playerModel.deselectAllCardsLocal();
				state = STATE_SELECT_RECT;
				selectRectangle = new SelectionBox();
				selectRectangle.setStart(e.getX(), e.getY());
				selectRectangle.setEnd(e.getX(), e.getY());
			} else {
				if(!playerModel.isSelectedCard(selectedCard)) {
					playerModel.deselectAllCardsLocal();
					playerModel.selectSingleCard(selectedCard);
				}
				System.out.println(selectedCard.getZ());

				

				if (e.isPopupTrigger()) {
					showContextMenu(e.getX(), e.getY());
				} else {
					playerModel.dragStart(e.getPoint());
				}

			}
			
		}
		
		public void mouseDragged(MouseEvent e) {
			translateMouse(e);
			
			switch (state) {
			
			case STATE_NORMAL:
				boolean movesuccess = playerModel.dragContinue(e.getPoint());
				
				break;
				
			//update selection rectangle
			case STATE_SELECT_RECT:
				selectRectangle.setEnd(e.getX(), e.getY());			 	
				
				CardSet selCards = new CardSet();
				for(Card card: playerModel.getCards()){
					
					if(card.getRectangle().intersects(selectRectangle)) {
						selCards.add(card);
					}
				}
				
				playerModel.selectCards(selCards);
				repaint();
				break;
			}
		}
		
		public void mouseReleased(MouseEvent e) {
			translateMouse(e);
			
			switch (state) {
			
			case STATE_NORMAL:
				playerModel.dragEnd(e.getPoint());
				break;
				
			case STATE_SELECT_RECT:
				state = STATE_NORMAL;
				repaint();
				break;
			}			
		}
		
		public void translateMouse(MouseEvent e) {
			e.translatePoint((int)(-e.getX() + e.getX() / at.getScaleX()), (int)(-e.getY() + e.getY() / at.getScaleY()));
		}
	}
	
	public void changeBackgroundColour(String colour) {
		if(colour.equals("green")) {
			this.setBackground(green);
		} else if(colour.equals("red")) {
			this.setBackground(red);
		} else if(colour.equals("blue")) {
			this.setBackground(blue);
		} else if(colour.equals("purple")) {
			this.setBackground(purple);
		}
		//this.repaint();
	}
	
	
	/**
	 * @param zoom the at to set
	 */
	public void zoom(int zoom) {
		
		double zin = 0.95;
		double zout = 1./zin;
		
		double zoomMax = 1.0;
		double zoomMin = 0.1;
		
		if (zoom>0) {
			zoomAmount *= zin;
		}
		if (zoom<0) {
			zoomAmount *= zout;
		}
		if(zoomEnable == true){
			zoomAmount = Math.min(zoomMax, zoomAmount);
			zoomAmount = Math.max(zoomMin, zoomAmount);
		}		
		at = AffineTransform.getScaleInstance(zoomAmount,zoomAmount);
		updatePanelSize();
	}
	
	public void setZoom(boolean z){
		zoomEnable = z;
	}
	
	
	//Scrolable methods
	public Dimension getPreferredScrollableViewportSize(){
		return new Dimension(800,600);
	}
	public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
		return 100;
	}
	
	public boolean getScrollableTracksViewportWidth(){
		return false;
	}
	
	public boolean getScrollableTracksViewportHeight(){
		return false;
	}
	public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
		return 10;
	}
	
	private void showContextMenu(int x, int y) {
		view.cardMenu.getPopupMenu().show(this, x, y);
	}
	
	
}



